package com.team2.insulatingtools.modular.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.stylefeng.roses.kernel.auth.api.context.LoginContext;
import cn.stylefeng.roses.kernel.auth.api.enums.DataScopeTypeEnum;
import cn.stylefeng.roses.kernel.auth.password.BcryptPasswordStoredEncrypt;
import cn.stylefeng.roses.kernel.expand.modular.api.ExpandApi;
import cn.stylefeng.roses.kernel.file.api.constants.FileConstants;
import cn.stylefeng.roses.kernel.rule.constants.SymbolConstant;
import cn.stylefeng.roses.kernel.rule.constants.TreeConstants;
import cn.stylefeng.roses.kernel.rule.enums.StatusEnum;
import cn.stylefeng.roses.kernel.rule.enums.YesOrNotEnum;
import cn.stylefeng.roses.kernel.rule.tree.factory.DefaultTreeBuildFactory;
import cn.stylefeng.roses.kernel.system.api.UserServiceApi;
import cn.stylefeng.roses.kernel.system.api.exception.SystemModularException;
import cn.stylefeng.roses.kernel.system.api.exception.enums.organization.OrganizationExceptionEnum;
import cn.stylefeng.roses.kernel.system.api.pojo.organization.HrOrganizationRequest;
import cn.stylefeng.roses.kernel.system.api.pojo.organization.OrganizationTreeNode;
import cn.stylefeng.roses.kernel.system.api.util.DataScopeUtil;
import cn.stylefeng.roses.kernel.system.modular.organization.entity.HrOrganization;
import cn.stylefeng.roses.kernel.system.modular.organization.service.impl.HrOrganizationServiceImpl;
import cn.stylefeng.roses.kernel.system.modular.user.entity.SysUser;
import cn.stylefeng.roses.kernel.system.modular.user.entity.SysUserOrg;
import cn.stylefeng.roses.kernel.system.modular.user.mapper.SysUserMapper;
import cn.stylefeng.roses.kernel.system.modular.user.mapper.SysUserOrgMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.team2.insulatingtools.modular.system.entity.ToolsHrOrganization;
import com.team2.insulatingtools.modular.system.entity.ToolsOrganizationTreeNode;
import com.team2.insulatingtools.modular.system.mapper.ToolsHrOrganizationMapper;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 重写原有组织机构操作逻辑
 * @author yangqian
 * @date 2023-04-03 11:36
 * @description
 **/
@Primary
@Service
public class ToolsHrOrganizationServiceImpl extends HrOrganizationServiceImpl {

    @Resource
    private ExpandApi expandApi;
    @Resource
    private BcryptPasswordStoredEncrypt passwordStoredEncrypt;
    @Resource
    private SysUserMapper userMapper;
    @Resource
    private SysUserOrgMapper orgMapper;

    @Resource
    private UserServiceApi userServiceApi;

    @Resource
    private ToolsHrOrganizationMapper toolsHrOrganizationMapper;

    private final String DEFAULT_PASSWORD = "Password@1234";

    private final String DEFAULT_SEX = "M";

    @Override
    public void add(HrOrganizationRequest hrOrganizationRequest) {
        // 获取父id
        Long pid = hrOrganizationRequest.getOrgParentId();

        // 校验数据范围
        DataScopeUtil.quickValidateDataScope(pid);

        ToolsHrOrganization hrOrganization = new ToolsHrOrganization();
        Map<String, Object> otherParams = hrOrganizationRequest.getOtherParams();
        hrOrganization.setSpeciality(this.join((List) otherParams.get("speciality")));
        hrOrganization.setIsWorkshop((Integer) otherParams.get("isWorkshop"));
        BeanUtil.copyProperties(hrOrganizationRequest, hrOrganization);

        // 填充parentIds
        this.fillParentIds(hrOrganization);

        // 设置状态为启用，未删除状态
        hrOrganization.setStatusFlag(StatusEnum.ENABLE.getCode());
        hrOrganization.setDelFlag("N");
        this.toolsHrOrganizationMapper.insert(hrOrganization);

        //新增用户
        // 请求bean转为实体，填充一些基本属性
        SysUser sysUser = new SysUser();
        sysUser.setAccount(hrOrganization.getOrgName());
        sysUser.setPassword(passwordStoredEncrypt.encrypt(DEFAULT_PASSWORD));
        sysUser.setNickName(hrOrganization.getOrgName());
        sysUser.setRealName(hrOrganization.getOrgName());
        sysUser.setAvatar(FileConstants.DEFAULT_AVATAR_FILE_ID);
        sysUser.setSex(DEFAULT_SEX);
        userMapper.insert(sysUser);

        //新增用户对应的机构
        SysUserOrg sysUserOrg = new SysUserOrg();
        sysUserOrg.setOrgId(hrOrganization.getOrgId());
        sysUserOrg.setUserId(sysUser.getUserId());
        orgMapper.insert(sysUserOrg);

        // 处理动态表单数据
        if (hrOrganizationRequest.getExpandDataInfo() != null) {
            hrOrganizationRequest.getExpandDataInfo().setPrimaryFieldValue(hrOrganization.getOrgId());
            expandApi.saveOrUpdateExpandData(hrOrganizationRequest.getExpandDataInfo());
        }

    }
    private ToolsHrOrganization queryOrganization(HrOrganizationRequest hrOrganizationRequest) {
        ToolsHrOrganization hrOrganization = toolsHrOrganizationMapper.selectById(hrOrganizationRequest.getOrgId());
        if (ObjectUtil.isEmpty(hrOrganization)) {
            throw new SystemModularException(OrganizationExceptionEnum.CANT_FIND_ORG, hrOrganizationRequest.getOrgId());
        }
        return hrOrganization;
    }

    private void fillParentIds(ToolsHrOrganization hrOrganization) {
        if (TreeConstants.DEFAULT_PARENT_ID.equals(hrOrganization.getOrgParentId())) {
            hrOrganization.setOrgPids(SymbolConstant.LEFT_SQUARE_BRACKETS + TreeConstants.DEFAULT_PARENT_ID + SymbolConstant.RIGHT_SQUARE_BRACKETS + SymbolConstant.COMMA);
        } else {
            // 获取父组织机构
            HrOrganizationRequest hrOrganizationRequest = new HrOrganizationRequest();
            hrOrganizationRequest.setOrgId(hrOrganization.getOrgParentId());
            HrOrganization parentOrganization = this.queryOrganization(hrOrganizationRequest);

            // 设置本节点的父ids为 (上一个节点的pids + (上级节点的id) )
            hrOrganization.setOrgPids(parentOrganization.getOrgPids() + SymbolConstant.LEFT_SQUARE_BRACKETS + parentOrganization.getOrgId() + SymbolConstant.RIGHT_SQUARE_BRACKETS + SymbolConstant.COMMA);
        }
    }

    @Override
    public void edit(HrOrganizationRequest hrOrganizationRequest) {
        ToolsHrOrganization hrOrganization = this.queryOrganization(hrOrganizationRequest);
        Long id = hrOrganization.getOrgId();
        DataScopeUtil.quickValidateDataScope(id);
        BeanUtil.copyProperties(hrOrganizationRequest, hrOrganization, new String[0]);
        this.fillParentIds(hrOrganization);
        hrOrganization.setStatusFlag((Integer)null);
        Map<String, Object> otherParams = hrOrganizationRequest.getOtherParams();
        hrOrganization.setSpeciality(this.join((List) otherParams.get("speciality")));
        hrOrganization.setIsWorkshop((Integer) otherParams.get("isWorkshop"));
        BeanUtil.copyProperties(hrOrganizationRequest, hrOrganization);
        this.toolsHrOrganizationMapper.updateById(hrOrganization);
        if (hrOrganizationRequest.getExpandDataInfo() != null) {
            hrOrganizationRequest.getExpandDataInfo().setPrimaryFieldValue(hrOrganization.getOrgId());
            this.expandApi.saveOrUpdateExpandData(hrOrganizationRequest.getExpandDataInfo());
        }

    }

    private String join(List<Integer> list){
        StringBuffer sb = new StringBuffer();
        if(list.size() > 0){
            for (Integer str:list) {
                sb.append(str).append(",");
            }
        }
        return sb.length() > 0 ? sb.substring(0,sb.length()-1):sb.toString();
    }

    @Override
    public List<OrganizationTreeNode> organizationTree(HrOrganizationRequest hrOrganizationRequest) {

        // 定义返回结果
        List<OrganizationTreeNode> treeNodeList = CollectionUtil.newArrayList();

        // 组装节点
        List<ToolsHrOrganization> hrOrganizationList = this.findListByDataScope(hrOrganizationRequest);
        for (ToolsHrOrganization hrOrganization : hrOrganizationList) {
            ToolsOrganizationTreeNode treeNode = parseOrganizationTreeNode(hrOrganization);
            treeNodeList.add(treeNode);
        }

        // 设置树节点上，用户绑定的组织机构数据范围
        if (hrOrganizationRequest.getUserId() != null) {
            List<Long> orgIds = userServiceApi.getUserBindDataScope(hrOrganizationRequest.getUserId());
            if (ObjectUtil.isNotEmpty(orgIds)) {
                for (OrganizationTreeNode organizationTreeNode : treeNodeList) {
                    for (Long orgId : orgIds) {
                        if (organizationTreeNode.getId().equals(orgId)) {
                            organizationTreeNode.setSelected(true);
                        }
                    }
                }
            }
        }

        if (ObjectUtil.isNotEmpty(hrOrganizationRequest.getOrgName()) || ObjectUtil.isNotEmpty(hrOrganizationRequest.getOrgCode())) {
            return treeNodeList;
        } else {
            return new DefaultTreeBuildFactory<OrganizationTreeNode>().doTreeBuild(treeNodeList);
        }
    }

    private List<ToolsHrOrganization> findListByDataScope(HrOrganizationRequest hrOrganizationRequest) {

        LambdaQueryWrapper<ToolsHrOrganization> queryWrapper = this.createWrapper(hrOrganizationRequest);

        // 数据范围过滤
        // 如果是超级管理员，或者数据范围权限是所有，则不过滤数据范围
        boolean needToDataScope = true;
        Set<DataScopeTypeEnum> dataScopeTypes = LoginContext.me().getLoginUser().getDataScopeTypeEnums();
        if (LoginContext.me().getSuperAdminFlag() || (dataScopeTypes != null && dataScopeTypes.contains(DataScopeTypeEnum.ALL))) {
            needToDataScope = false;
        }

        // 过滤数据范围的SQL拼接
        if (needToDataScope) {
            // 获取用户数据范围信息
            Set<Long> dataScope = LoginContext.me().getLoginUser().getDataScopeOrganizationIds();

            // 如果数据范围为空，则返回空数组
            if (ObjectUtil.isEmpty(dataScope)) {
                return new ArrayList<>();
            }

            // 根据组织机构数据范围的上级组织，用于展示完整的树形结构
            Set<Long> allLevelParentIdsByOrganizations = this.findAllLevelParentIdsByOrganizations(dataScope);
            // 拼接查询条件
            queryWrapper.in(HrOrganization::getOrgId, allLevelParentIdsByOrganizations);
        }

        return this.toolsHrOrganizationMapper.selectList(queryWrapper);
    }

    private LambdaQueryWrapper<ToolsHrOrganization> createWrapper(HrOrganizationRequest hrOrganizationRequest) {
        LambdaQueryWrapper<ToolsHrOrganization> queryWrapper = new LambdaQueryWrapper<>();

        // 查询未删除状态的
        queryWrapper.eq(HrOrganization::getDelFlag, YesOrNotEnum.N.getCode());

        // 根据排序升序排列，序号越小越在前
        queryWrapper.orderByAsc(HrOrganization::getOrgSort);

        if (ObjectUtil.isEmpty(hrOrganizationRequest)) {
            return queryWrapper;
        }

        String orgName = hrOrganizationRequest.getOrgName();
        String orgCode = hrOrganizationRequest.getOrgCode();
        Long orgParentId = hrOrganizationRequest.getOrgParentId();
        Long orgId = hrOrganizationRequest.getOrgId();
        Integer orgType = hrOrganizationRequest.getOrgType();
        String taxNo = hrOrganizationRequest.getTaxNo();

        // 拼接组织机构名称条件
        queryWrapper.like(ObjectUtil.isNotEmpty(orgName), HrOrganization::getOrgName, orgName);

        // 拼接组织机构编码条件
        queryWrapper.like(ObjectUtil.isNotEmpty(orgCode), HrOrganization::getOrgCode, orgCode);

        // 组织机构类型拼接
        queryWrapper.eq(ObjectUtil.isNotEmpty(orgType), HrOrganization::getOrgType, orgType);

        // 税号查询条件
        queryWrapper.eq(StrUtil.isNotEmpty(taxNo), HrOrganization::getTaxNo, taxNo);

        // 拼接父机构id查询条件
        if (ObjectUtil.isNotEmpty(orgParentId)) {
            queryWrapper.and(qw -> {
                qw.eq(HrOrganization::getOrgId, orgParentId).or().like(HrOrganization::getOrgPids, orgParentId);
            });
        }

        // 拼接机构id查询条件
        queryWrapper.eq(ObjectUtil.isNotEmpty(orgId), HrOrganization::getOrgId, orgId);

        // 拼接限制查询范围列表
        List<Long> orgIdLimit = hrOrganizationRequest.getOrgIdLimit();
        if (ObjectUtil.isNotEmpty(orgIdLimit)) {
            queryWrapper.nested(qw -> {
                for (Long itemOrgId : orgIdLimit) {
                    qw.or().like(HrOrganization::getOrgPids, itemOrgId);
                }
            });
        }

        return queryWrapper;
    }


    public static ToolsOrganizationTreeNode parseOrganizationTreeNode(ToolsHrOrganization hrOrganization) {
        ToolsOrganizationTreeNode treeNode = new ToolsOrganizationTreeNode();
        treeNode.setId(hrOrganization.getOrgId());
        treeNode.setParentId(hrOrganization.getOrgParentId());
        treeNode.setTitle(hrOrganization.getOrgName());

        treeNode.setOrgName(hrOrganization.getOrgName());
        treeNode.setOrgCode(hrOrganization.getOrgCode());
        treeNode.setStatusFlag(hrOrganization.getStatusFlag());
        treeNode.setOrgSort(hrOrganization.getOrgSort());
        treeNode.setOrgRemark(hrOrganization.getOrgRemark());
        treeNode.setOrgType(hrOrganization.getOrgType());
        treeNode.setIsWorkshop(hrOrganization.getIsWorkshop());
        treeNode.setSpeciality(hrOrganization.getSpeciality());
        return treeNode;
    }

    @Override
    public HrOrganization detail(HrOrganizationRequest hrOrganizationRequest) {
        return this.toolsHrOrganizationMapper.selectOne(this.createWrapper(hrOrganizationRequest));
    }
}
